#include "av_player_core.h"
#include "utils_log.h"
#include "av_player_common.h"
#include <chrono>
#include <thread>
#include <android/log.h>
#include <atomic>
#include <condition_variable>
#include <mutex>
extern "C" {
#include "libavutil/time.h"
}

#define LOG_TAG "AVPlayerCore"

// 日志配置
static const LogOutput LOG_OUTPUT = LogOutput::CONSOLE;
static const LogLevel LOG_LEVEL = LogLevel::VERBOSE;
static const std::string DEFAULT_TAG = "AVPlayer";
static const std::string LOG_PATH = "";

AVPlayerCore::AVPlayerCore() {
    static std::once_flag log_init_flag;
    std::call_once(log_init_flag, []() {
        bool init_result = getMcLogTool().init(
                LOG_OUTPUT, LOG_LEVEL, DEFAULT_TAG, LOG_PATH
        );
        if (!init_result) {
            __android_log_write(ANDROID_LOG_ERROR, LOG_TAG, "Log tool init failed! Fallback to Android log.");
            McLogTool::getInstance().init(LogOutput::CONSOLE, LogLevel::ERROR, DEFAULT_TAG, "");
        }
    });

    LOGD(LOG_TAG, "AVPlayerCore instance created");
}

AVPlayerCore::~AVPlayerCore() {
    LOGD(LOG_TAG, "Destructing AVPlayerCore");

    stopPlayback();
}

void AVPlayerCore::setStatusCallback(StateCallback callback) {
    std::lock_guard<std::mutex> lock(core_mutex_);
    state_callback_ = callback;
}

void AVPlayerCore::initialize(const std::string& url, ANativeWindow* window) {
    std::lock_guard<std::mutex> lock(core_mutex_);
    releaseComponents();    // 清空可能残留的资源
    media_url_ = url;
    native_window_ = window;

    // 保证干掉之前的线程
    if (worker_thread_.joinable()) {
        state_.store(MediaState::STOPPED);
        core_cv_.notify_one();
        worker_thread_.join();
        worker_thread_ = std::thread();
    }
    worker_thread_ = std::thread(&AVPlayerCore::workerMain, this);
}

void AVPlayerCore::startPlayback() {
    std::lock_guard<std::mutex> lock(core_mutex_);
    MediaState current = state_.load();
    if (current != MediaState::STOPPED && current != MediaState::PAUSED && current != MediaState::READY) {
        LOGE(LOG_TAG, "startPlayback failed: invalid state=", current);
        return;
    }
    if (renderer_) {
        renderer_->start();
    }
    updateState(MediaState::RUNNING);

    core_cv_.notify_one();
}

void AVPlayerCore::pausePlayback() {
    std::lock_guard<std::mutex> lock(core_mutex_);
    if (state_.load() != MediaState::RUNNING) {
        LOGD(LOG_TAG, "pausePlayback ignored: state=", state_.load());
        return;
    }
    if (renderer_) {
        renderer_->pause();
    }
    updateState(MediaState::PAUSED);

    core_cv_.notify_one();
}

void AVPlayerCore::stopPlayback() {
    {
        std::lock_guard<std::mutex> lock(core_mutex_);
        MediaState current = state_.load();
        if (current == MediaState::STOPPED || current == MediaState::IDLE) {
            LOGD(LOG_TAG, "stopPlayback ignored: state=", current);
            return;
        }
        if (renderer_) {
            renderer_->stop();
        }
        updateState(MediaState::STOPPED);
    }
    core_cv_.notify_one();

    if (worker_thread_.joinable()) {
        worker_thread_.join();
        worker_thread_ = std::thread();
    }
}

void AVPlayerCore::seekTo(int64_t us) {
    std::lock_guard<std::mutex> lock(core_mutex_);
    MediaState current = state_.load();
    if (current != MediaState::RUNNING && current != MediaState::PAUSED) {
        LOGE(LOG_TAG, "seekTo failed: invalid state=", current);
        return;
    }

    if (us < 0 || (media_info_->duration_us > 0 && us > media_info_->duration_us)) {
        LOGE(LOG_TAG, "seekTo out of range: us=", us, ", duration=", media_info_->duration_us);
        return;
    }

    if (is_seeking_) {
        LOGW(LOG_TAG, "Already seeking, ignore new request");
        return;
    }

    is_seeking_ = true;
    seek_target_us_ = us;
    core_cv_.notify_one();
}

void AVPlayerCore::workerMain() {
    LOGI(LOG_TAG, "Worker thread started (ID=", std::this_thread::get_id(), ")");

    // 加载资源
    {
        std::lock_guard<std::mutex> lock(core_mutex_);
        if (initComponents()) {
            updateState(MediaState::READY);
        } else {
            updateState(MediaState::ERROR);
        }
    }

    LOGV(LOG_TAG, "Worker thread ready");

    // 处理播放循环
    playbackLoop();

    LOGV(LOG_TAG, "Worker thread loop finish");

    // 释放资源
    {
        std::lock_guard<std::mutex> lock(core_mutex_);
        releaseComponents();
        updateState(MediaState::IDLE);
    }

    LOGI(LOG_TAG, "Worker thread exited");
}

bool AVPlayerCore::initComponents() {
    LOGV(LOG_TAG, "initComponents");

    if (!initDecoder()) {
        LOGE(LOG_TAG, "Decoder initialization failed");
        return false;
    }

    if (!initFilter()) {
        LOGE(LOG_TAG, "Filter initialization failed");
        releaseComponents();
        return false;
    }

    if (!initRenderer()) {
        LOGE(LOG_TAG, "Renderer initialization failed");
        releaseComponents();
        return false;
    }

    return true;
}

bool AVPlayerCore::initDecoder() {
    if (media_url_.empty()) {
        LOGE(LOG_TAG, "initDecoder failed: media_url is empty");
        return false;
    }

    // 音频配置
    decoder_config_.config_audio.codec_type = CodecType::CODEC_SW;

    // 视频配置
    decoder_config_.config_video.codec_type = CodecType::CODEC_SW;
//    decoder_config_.config_video.window_handle = (uintptr_t)native_window_;

    decoder_ = McDecoderAPI::create(media_url_, decoder_config_);
    if (!decoder_) {
        LOGE(LOG_TAG, "Failed to create decoder");
        return false;
    }

    McCodecMsg ret = decoder_->initialize();
    if (ret != McCodecMsg::MC_CODEC_SUCCESS) {
        LOGE(LOG_TAG, "Decoder initialize failed with code=", ret);
        McDecoderAPI::destroy(decoder_);
        decoder_ = nullptr;
        return false;
    }

    media_info_ = decoder_->getMediaInfo();

    for (const auto & i : media_info_->detail) {
        if (i.first == McMediaStreamType::VIDEO) {
            const McMediaInfoVideo* info_video = (McMediaInfoVideo*)i.second;
            is_through_ = info_video != nullptr && info_video->through;
        }
        std::queue<AVFrame*> queue_;
        frames_decode_.emplace_back(i.first, queue_);
        stream_eof_.push_back(false);
        active_decode_streams_++;
    }

    LOGI(LOG_TAG, "Media duration=", media_info_->duration_us, " us, stream count=", media_info_->detail.size());
    return true;
}

bool AVPlayerCore::initFilter() {
    for (auto info : media_info_->detail) {
        if (info.first == McMediaStreamType::AUDIO) {
            const McMediaInfoAudio* info_audio = (McMediaInfoAudio*)info.second;
            filter_config_audio_.desc = "[in] aformat=sample_fmts=s16:channel_layouts=stereo [out]";
            filter_config_audio_.time_base = info_audio->time_base;
            filter_config_.detail.emplace_back(McMediaStreamType::AUDIO, &filter_config_audio_);
        }
        if (info.first == McMediaStreamType::VIDEO) {
            const McMediaInfoVideo* info_video = (McMediaInfoVideo*)info.second;
            filter_config_video_.desc = "[in] format=rgb24 [out]";
            filter_config_video_.time_base = info_video->time_base;
            filter_config_.detail.emplace_back(McMediaStreamType::VIDEO, &filter_config_video_);
        }
        std::queue<AVFrame*> queue_;
        frames_filter_.emplace_back(info.first, queue_);
    }
    filter_ = McFilterAPI::create(filter_config_);
    if (!filter_) {
        LOGE(LOG_TAG, "Failed to create filter manager");
        return false;
    }

    McCodecMsg ret = filter_->initialize();
    if (ret != McCodecMsg::MC_CODEC_SUCCESS) {
        LOGE(LOG_TAG, "Filter initialize failed with code=", ret);
        McFilterAPI::destroy(filter_);
        filter_ = nullptr;
        return false;
    }

    return true;
}

bool AVPlayerCore::initRenderer() {
    for (auto info : media_info_->detail) {
        if (info.first == McMediaStreamType::AUDIO) {
            const McMediaInfoAudio* info_audio = (McMediaInfoAudio*)info.second;
            render_config_audio_.sample_rate = info_audio->sample_rate;
            render_config_audio_.channels = 2;  // 过滤器之后
            render_config_audio_.format = AV_SAMPLE_FMT_S16;    // 过滤器之后
            render_config_.detail.emplace_back(McRenderStreamType::AUDIO, &render_config_audio_);
        }
        if (info.first  == McMediaStreamType::VIDEO) {
            const McMediaInfoVideo* info_video = (McMediaInfoVideo*)info.second;
            render_config_video_.width = info_video->width;
            render_config_video_.height = info_video->height;
            render_config_video_.fps = info_video->frame_rate.num;
            if (is_through_) {
                render_config_video_.window_handle = 0;
            } else {
                render_config_video_.window_handle = reinterpret_cast<uintptr_t>(native_window_);
            }
            render_config_.detail.emplace_back(McRenderStreamType::VIDEO, &render_config_video_);
        }
    }

    renderer_ = McRenderAPI::create(render_config_);
    if (!renderer_) {
        LOGE(LOG_TAG, "Failed to create decoder");
        return false;
    }

    renderer_->setRenderCallback(&render_callback_);

    McRenderMsg ret = renderer_->init();
    if (ret != McRenderMsg::MC_RENDER_SUCCESS) {
        LOGE(LOG_TAG, "Renderer init failed with code=", ret);
        McRenderAPI::destroy(renderer_);
        renderer_ = nullptr;
        return false;
    }

    return true;
}

void AVPlayerCore::playbackLoop() {
    LOGI(LOG_TAG, "Playback loop started (thread id=", std::this_thread::get_id(), ")");

    while (true) {
        // 主等待逻辑：根据当前状态决定是否阻塞
        {
            std::unique_lock<std::mutex> lock(core_mutex_);
            // 等待条件：需要处理seek、状态为运行中或需要退出
            core_cv_.wait(lock, [this]() {
                MediaState current = state_.load();
                return is_seeking_ || current == MediaState::RUNNING
                       || current == MediaState::STOPPED || current == MediaState::ERROR;
            });

            // 检查退出条件
            MediaState current = state_.load();
            if (current == MediaState::STOPPED || current == MediaState::ERROR) {
                LOGI(LOG_TAG, "Playback loop exit condition met, state=", current);
                break;
            }
            if (current == MediaState::PAUSED) {
                continue;
            }
        }

        // 处理seek操作
        int64_t seek_pos = -1;
        {
            std::lock_guard<std::mutex> lock(core_mutex_);
            if (is_seeking_ && decoder_) {
                seek_pos = seek_target_us_;
                is_seeking_ = false; // 标记seek开始处理
            }
        }
        if (seek_pos != -1) {
            LOGI(LOG_TAG, "Seeking to us=", (long long)seek_pos);
            McCodecMsg ret = decoder_->seekTo(seek_pos);
            if (ret == McCodecMsg::MC_CODEC_SUCCESS) {
                if (filter_) filter_->flush();
                if (renderer_) renderer_->seekTo(seek_pos);
                clearFrameQueues();
                LOGI(LOG_TAG, "Seek succeeded");
            } else {
                LOGE(LOG_TAG, "Seek failed with code=", ret);
                std::lock_guard<std::mutex> lock(core_mutex_);
                updateState(MediaState::ERROR);
                continue; // 出错后继续循环等待处理
            }
        }

        // 只有在运行状态才处理帧数据
        {
            std::lock_guard<std::mutex> lock(core_mutex_);
            if (state_.load() != MediaState::RUNNING) {
                continue;
            }
        }

        // 解码渲染数据帧
        if (!decodeFrames() & !filterFrames() & !renderFrames()) {
            std::lock_guard<std::mutex> lock(core_mutex_);
            updateState(MediaState::STOPPED);
        }

        // 控制播放速率，减少CPU占用
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }

    LOGI(LOG_TAG, "Playback loop exited");
}

bool AVPlayerCore::decodeFrames() {
    if (!decoder_) {
        LOGV(LOG_TAG, "decodeFrames failed: null components");
        return false;
    }

    //seek时候立刻停止
    if (is_seeking_) {
        return true;
    }

    if (active_decode_streams_ == 0) {
        return false;
    }

    McCodecMsg msgCodec = decoder_->driveOnce();
    if (msgCodec != McCodecMsg::MC_CODEC_SUCCESS) {
        LOGW(LOG_TAG, "Decode drive failed with message=", msgCodec);
    }

    for (int i = 0; i < frames_decode_.size(); i++) {
        if (is_seeking_) {
            break;
        }

        if (stream_eof_[i]) {
            continue;
        }

        if ((frames_decode_[i].first == McMediaStreamType::AUDIO && frames_decode_[i].second.size() > BUFFER_QUEUE_SIZE_AUDIO_PLAYER) ||
            (frames_decode_[i].first == McMediaStreamType::VIDEO && frames_decode_[i].second.size() > BUFFER_QUEUE_SIZE_VIDEO_PLAYER) ) {
            continue;
        }

        AVFrame* frame = av_frame_alloc();
        msgCodec = decoder_->fetchFrame(frame, i);
        if (msgCodec == McCodecMsg::MC_CODEC_SUCCESS) {
            frames_decode_[i].second.push(frame);
        } else {
            av_frame_free(&frame);
            if (msgCodec == McCodecMsg::MC_CODEC_ERROR_EOF) {
                stream_eof_[i] = true;
                active_decode_streams_--;
            }
        }
    }

    return true;
}

bool AVPlayerCore::filterFrames() {
    if (!filter_) {
        LOGV(LOG_TAG, "filterFrames failed: null components");
        return false;
    }

    for (int i = 0; i < frames_decode_.size(); i++) {
        if (is_seeking_) {
            break;
        }

        if (frames_decode_[i].second.empty()) {
            continue;
        }

        // 硬编直通，不送过滤器
        if (frames_decode_[i].first == McMediaStreamType::VIDEO && is_through_) {
            frames_filter_[i].second.push(frames_decode_[i].second.front());
            frames_decode_[i].second.pop();
            continue;
        }

        McCodecMsg msgCodec = filter_->pushFrame(frames_decode_[i].second.front(), i);
        if (msgCodec == McCodecMsg::MC_CODEC_SUCCESS) {
            frames_decode_[i].second.pop();
        }
    }

    bool is_empty = true;
    for (int i = 0; i < frames_filter_.size(); i++) {
        if (is_seeking_) {
            break;
        }

        // 硬编直通，已处理
        if (frames_decode_[i].first == McMediaStreamType::VIDEO && is_through_) {
            continue;
        }

        if ((frames_filter_[i].first == McMediaStreamType::AUDIO && frames_filter_[i].second.size() > BUFFER_QUEUE_SIZE_AUDIO_PLAYER) ||
            (frames_filter_[i].first == McMediaStreamType::VIDEO && frames_filter_[i].second.size() > BUFFER_QUEUE_SIZE_VIDEO_PLAYER) ) {
            continue;
        }

        AVFrame* frame = filter_->receiveFrame(i);
        if (frame) {
            frames_filter_[i].second.push(frame);
        }

        is_empty &= frames_filter_[i].second.empty();
    }

    return !is_empty;
}

bool AVPlayerCore::renderFrames() {
    if (!renderer_ ) {
        LOGV(LOG_TAG, "renderFrames failed: null components");
        return false;
    }

    //seek时候立刻停止
    if (is_seeking_) {
        return true;
    }

    bool is_empty = true;
    renderer_->getBufferSize(buffer_size_render_[0], buffer_size_render_[1]);
    for (auto& frame_filter : frames_filter_) {
        if (frame_filter.second.empty()) {
            continue;
        }

        // 硬编直通，送渲染器做同步后直接处理
        if (frame_filter.first == McMediaStreamType::VIDEO && is_through_) {
            renderer_->pushFrame(frame_filter.second.front(), McRenderStreamType::VIDEO);
            av_frame_unref(frame_filter.second.front());
            frame_filter.second.pop();
        }

        if (frame_filter.first == McMediaStreamType::AUDIO &&
            render_callback_.getCountBufferAudio() < BUFFER_QUEUE_SIZE_AUDIO_RENDER) {
            if (renderer_->pushFrame(frame_filter.second.front(), McRenderStreamType::AUDIO) == McRenderMsg::MC_RENDER_SUCCESS) {
                frame_filter.second.pop();
            }
        }
        if (frame_filter.first == McMediaStreamType::VIDEO &&
            render_callback_.getCountBufferVideo() < BUFFER_QUEUE_SIZE_VIDEO_RENDER) {
            if (renderer_->pushFrame(frame_filter.second.front(), McRenderStreamType::VIDEO) == McRenderMsg::MC_RENDER_SUCCESS) {
                frame_filter.second.pop();
            }
        }
        is_empty = false;
    }

    return !is_empty;
}

void AVPlayerCore::clearFrameQueues() {
    if (!media_info_) return;

    for (auto& frame_decode : frames_decode_) {
        while (!frame_decode.second.empty()) {
            av_frame_free(&frame_decode.second.front());
            frame_decode.second.pop();
        }
    }

    for (auto& frame_filter : frames_filter_) {
        while (!frame_filter.second.empty()) {
            av_frame_free(&frame_filter.second.front());
            frame_filter.second.pop();
        }
    }
}

void AVPlayerCore::releaseComponents() {
    LOGD(LOG_TAG, "releaseComponents");

    clearFrameQueues();
    frames_decode_.clear();
    frames_filter_.clear();
    stream_eof_.clear();

    is_seeking_ = false;
    seek_target_us_ = 0;
    active_decode_streams_ = 0;

    if (renderer_) {
        McRenderAPI::destroy(renderer_);
        renderer_ = nullptr;
    }

    if (filter_) {
        McFilterAPI::destroy(filter_);
        filter_ = nullptr;
    }

    if (decoder_) {
        McDecoderAPI::destroy(decoder_);
        decoder_ = nullptr;
    }

    media_info_ = nullptr;
}

void AVPlayerCore::updateState(MediaState new_state) {
    if (state_.load() == new_state) return;

    LOGD(LOG_TAG, "State changed ", state_.load(), " to " , new_state);
    state_.store(new_state);

    if (state_callback_) {
        state_callback_(new_state, this);
    }
}